#include <iostream>
#include <iterator>
#include <algorithm>
#include <functional>
#include <vector>

#include <boost/function.hpp>
#include <boost/bind.hpp>

using namespace std;
using namespace boost;

void test_iostream_iterator();
void test_function_adapt();

int main()
{
    test_iostream_iterator();
    test_function_adapt();
    return 0;
}

void test_iostream_iterator()
{
    ostream_iterator<int> out_iter(cout, " ");
    int ia[6] = {2, 21, 12, 7, 19, 23};
    vector<int> iv(ia, ia+6);
    copy(iv.begin(), iv.end(), out_iter);
    cout << endl;
}

struct AA {
    AA(int v) : _value(v) {}
    int getValue() {
        return _value;
    }
private:
    int _value;
};

struct BB {
    BB(AA *a) : _AA(a) {}
    AA* getA() {
        return _AA; 
    }
private:
    AA* _AA;
};

int GetValue_ptr (BB *b) {
    return b->getA()->getValue();
}

template <class Operation1, class Operation2>
class unary_compose
    : public unary_function<typename Operation2::argument_type, 
                            typename Operation1::result_type>
{
protected:
    Operation1 op1;
    Operation2 op2;
public:
    unary_compose(const Operation1 &x, const Operation2 &y)
        : op1(x), op2(y) {}
    typename Operation1::result_type
    operator () (const typename Operation2::argument_type &x) const {
        return op1(op2(x));
    }
};

template <class Operation1, class Operation2>
inline unary_compose<Operation1, Operation2>
compose1(const Operation1 &op1, const Operation2 &op2) {
    return unary_compose<Operation1, Operation2>(op1, op2);
}

void test_function_adapt()
{
    AA a(23);
    BB b(&a);

    cout << GetValue_ptr(&b) << endl;;

    typedef mem_fun_t<AA*, BB> Func1;
    typedef mem_fun_t<int, AA> Func2;
    unary_compose<Func2, Func1> GetValue_stl = compose1(mem_fun(&AA::getValue), mem_fun(&BB::getA));
    cout << GetValue_stl(&b) << endl;

    function<int (BB*)> GetValue_boost = bind(&AA::getValue, bind(&BB::getA, _1));
    cout << GetValue_boost(&b) << endl;
}
